﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace Engine.NetClasses
{
    


    public class NetPacket
    {
        /// <summary>
        /// Список пакетов
        /// </summary>
        static Dictionary<byte, IPacket> _packets;
        /// <summary>
        /// Добавление нового пакета
        /// </summary>
        /// <param name="packet">Пакет реализующий интерфейс Engine.NetClasses.IPacket</param>
        /// <returns>True если добавление удачно
        /// False если пакет с таким типом уже существует
        /// </returns>
        public static bool Add(IPacket packet)
        {
            if (!_packets.ContainsKey(packet.PacketType))
            {
                _packets.Add(packet.PacketType,packet);
                return true;
            }
            return false;
        }
        /// <summary>
        /// Удаление пакета по типу
        /// </summary>
        /// <param name="packetType">Тип пакета байт</param>
        /// <returns>True если удаление удачно
        /// False если пакет с таким типом не существует</returns>
        public static bool Remove(byte packetType)
        {
            if (_packets.ContainsKey(packetType))
            {
                _packets.Remove(packetType);
                return true;
            }
            return false;
        }
        /// <summary>
        /// Получить структуру по типу пакета
        /// </summary>
        /// <param name="PacketType"> тип пакета</param>
        /// <returns>Структура пакета</returns>
        public static IPacket GetPacket(byte PacketType)
        {
            if (_packets.ContainsKey(PacketType))
            {
                return _packets[PacketType];
                
            }
            return GetPacket(0);
        }

        /// <summary>
        /// Получить Структуру пакета из данных
        /// первые 2 байта размер пакета
        /// 3 байт тип пакета
        /// далее данные
        /// </summary>
        /// <param name="data">данные</param>
        /// <returns>Структуру текушего пакета либо Нулевой пакет</returns>
        public static IPacket GetPacket(byte[] data)
        {
            byte _TYPE = data[2];
            IPacket temp = GetPacket(_TYPE);
            if (temp.GetType()!=typeof(NullPacket))
            {
                 temp.Convert(data);
            }           
            return temp;


        }

        /// <summary>
        /// Конструктор
        /// </summary>
        /// <param name="useDeffault">Заполнять стандартными протоколами</param>
        public static void NetPacketBild(bool useDeffault=true)
        {
            Helpers.Crypter.Init();
            _packets = new Dictionary<byte, IPacket>();
            _packets.Add(0,new NullPacket(true,true,0));
            if (useDeffault)
            {
                AddStandartProtocol();
            }
            else
            {
                _packets.Clear();
                _packets.Add(0, new NullPacket(true, true, 0));
            }

        }

        /// <summary>
        /// Заполнение стандартными пакетами
        /// </summary>
        private static void AddStandartProtocol()
        {
            _packets.Add((byte)PacketType.Init, new Init(false, true, (byte)PacketType.Init));
            _packets.Add((byte)PacketType.LoginOk, new LoginOk(false, true, (byte)PacketType.LoginOk));
            _packets.Add((byte)PacketType.RequestLoginAuth, new RequestLoginAuth(true, false, (byte)PacketType.RequestLoginAuth));
            _packets.Add((byte)PacketType.LoginFail, new LoginFail(false, true, (byte)PacketType.LoginFail));
            _packets.Add((byte)PacketType.NetPing, new NetPing(true, true, (byte)PacketType.NetPing));
            _packets.Add((byte)PacketType.RequestServerList, new RequestServerList(true, false, (byte)PacketType.RequestServerList));
            _packets.Add((byte)PacketType.ServerList, new ListServer(false, true, (byte)PacketType.ServerList));
            _packets.Add((byte)PacketType.RequestGame, new RequestGame(true, false, (byte)PacketType.RequestGame));

        }
    }
}
